package cn.qinhao.pethome.basic.interceptor;

import cn.qinhao.pethome.annotation.PreAuthorize;
import cn.qinhao.pethome.basic.base.BaseConstants;
import cn.qinhao.pethome.employee.domain.Employee;
import cn.qinhao.pethome.employee.service.IEmployeeService;
import cn.qinhao.pethome.login.domain.Logininfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IEmployeeService employeeService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        try {
            //1.获取请求头
            String token = request.getHeader("Token");
            //防止下面获取不到报非空密钥，
            if(token==null){
                errorResult(response,"NoLogin");
            }
            //2.校验token——根据token获取redis的值
            Object ObjToken = redisTemplate.opsForValue().get(token);
            if(ObjToken!=null){
                Logininfo logininfo =  (Logininfo) ObjToken;
                //刷新token过期时间，放行（每一次请求都要进入拦截器，所以请求一次刷新一次）
                redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
                //检查是否有权限
                boolean isCheck = permissionCheck(logininfo, handler);//权限检查
                if(!isCheck){
                    errorResult(response,"NoPermission");
                    return false;
                }
                return true;
            }
        } catch (Exception e) {
            //第一次获取token为空会出现异常，所以捕获一下，防止非空密钥
            e.printStackTrace();
            errorResult(response,"NoLogin");
            return false;
        }
        //如果为空获取不到值返回错误信息
        errorResult(response,"NoLogin");
        return false;
    }
    //检查权限的方法
    private boolean permissionCheck(Logininfo logininfo,Object handler) {
        /* HandlerMethod封装了很多属性，
         *在访问请求方法的时候可以方便的访问到方法、方法参数、方法上的注解、所属类等并且对方法参数封装处理
         *也可以方便的访问到方法参数的注解等信息。
         */
        //1、检查是否需要拦截
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //获取请求方法上的注解对象，如果为空就没有设置权限就放行
        PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
        if(preAuthorize==null){
            return true;
        }
        //不为空
            //获取到唯一标识的sn,通过sn去和redis里面的作比较，有就放行，没有就不放行
        String sn = preAuthorize.value();
        //看是管理员还是用户（根据传入的logininfo获取id去查）
        Long id = logininfo.getId();
        if(logininfo.getType()==BaseConstants.logininfo.STATE_type_admin){
            //通过管理员的id获取权限信息
            Employee employee = employeeService.loadByLogininfo(id);
            List<String> snList = employeeService.loadPermissionByEmpId(employee.getId());
            //比较是否含有权限
            if(!snList.contains(sn)){
                return false;
            }
        }else{
            //用户，没写直接放回true
            return true;
        }
        return true;
    }
    private void errorResult(HttpServletResponse response,String msg) throws IOException {
        // 登录失效通过响应返回错误信息
        PrintWriter writer = response.getWriter();//tomcat
        writer.println("{\"success\":false,\"message\":\""+msg+"\"}");
        writer.flush();
        writer.close();
    }

}


